package com.dailyblue.java.spring.boot.security.config;

import com.dailyblue.java.spring.boot.security.filter.CheckLoginFilter;
import com.dailyblue.java.spring.boot.security.filter.SecurityLoginFilter;
import com.dailyblue.java.spring.boot.security.handler.FailureLoginHandler;
import com.dailyblue.java.spring.boot.security.handler.NotLoginHandler;
import com.dailyblue.java.spring.boot.security.handler.SuccessLoginHandler;
import com.dailyblue.java.spring.boot.security.mapper.PowersMapper;
import com.dailyblue.java.spring.boot.security.service.UsersService;
import com.dailyblue.java.spring.boot.security.service.impl.UsersServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.Resource;

@Configuration
@Slf4j
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UsersServiceImpl usersServiceImpl;
    @Resource
    private NotLoginHandler notLoginHandler;
    @Resource
    private SuccessLoginHandler successLoginHandler;
    @Resource
    private FailureLoginHandler failureLoginHandler;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private PowersMapper powersMapper;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        log.info("SecurityConfig`configure方法1");
        /*PasswordEncoder passwordEncoder = getPasswordEncoder();
        String user = "admin";
        String pass = passwordEncoder.encode("123456");
        log.info("账号：{}，密码：{}", user, pass);
        auth.inMemoryAuthentication().withUser(user).password(pass).roles("admin");*/
        auth.userDetailsService(usersServiceImpl).passwordEncoder(getPasswordEncoder());
    }

    // 自定义登录页面
    /*protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()   //自定义登陆页面
                //.loginPage("/login.html") //登录页面设置
                .loginProcessingUrl("/user/login")     //登陆访问路径  这里同 action
                //.defaultSuccessUrl("/index.html").permitAll()   //登陆成功之后，跳转路径
                //.successHandler(successLoginHandler)
                //.failureHandler(failureLoginHandler)
                .and()
                .addFilter(new SecurityLoginFilter()).httpBasic().and()
                //.exceptionHandling().accessDeniedPage("/403.html")
                .exceptionHandling().authenticationEntryPoint(notLoginHandler)
                .and().authorizeRequests()
                .antMatchers("/login.html", "/user/login").permitAll()  //设置哪些路径可以直接访问，不需要认证
                .antMatchers("/1.html").hasAuthority("/users/find")
                .antMatchers("/2.html").hasAnyAuthority("/users/delete", "/powers/find_power")
                .antMatchers("/3.html").hasAnyAuthority("/users/find", "/users/update")
                .antMatchers("/4.html").hasAnyRole("roleA")
                .anyRequest().authenticated()   //所有请求都可以访问
                .and()
                .csrf().disable();  //关闭csrf
    }*/

    protected void configure(HttpSecurity http) throws Exception {
        log.info("SecurityConfig`configure方法2");
        http.exceptionHandling()
                .authenticationEntryPoint(notLoginHandler) // 未登录 handler
                .and().csrf().disable() // 关闭 csrf 跨域请求
                .cors().and()    // security允许跨域
                .formLogin()
                .loginProcessingUrl("/user/login")  // 设定登录请求接口
                .usernameParameter("username")
                .passwordParameter("password")
                .permitAll()
                .and()
                .authorizeRequests() // 请求设置
                .antMatchers("/login.html", "/user/login").permitAll() // 配置不需要认证的接口
                .anyRequest().authenticated() // 任何请求都需要认证
                .and()
                .addFilter(new SecurityLoginFilter(this.authenticationManager(), stringRedisTemplate)) // 认证交给 自定义 TokenLoginFilter 实现
                .addFilter(new CheckLoginFilter(this.authenticationManager(),stringRedisTemplate,powersMapper))
                .httpBasic();
    }


    @Bean(name = "passwordEncoder")
    PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
